/* * 
 * File: ChildManager.java
 * @author: Adam Phung
 * @author: Abdelghani Bhalla
 * Email: adam.phung@gmail.com
 * Date Created:
 * Date Modified: Nov 2, 2012 
 * Description:
 */

package edu.bu.cs673.superkids123.common.DataObjectAccess;

import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import edu.bu.cs673.superkids123.HibernateUtil;
import edu.bu.cs673.superkids123.children.model.Activity;
import edu.bu.cs673.superkids123.children.model.CompletedGame;
import edu.bu.cs673.superkids123.children.model.CompletedLesson;
import edu.bu.cs673.superkids123.children.model.Level;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.common.model.Achievement;
import edu.bu.cs673.superkids123.common.model.Child;
import edu.bu.cs673.superkids123.common.model.Child.Sex;
import edu.bu.cs673.superkids123.parents.DataObjectAccess.ParentSystemManager;
import edu.bu.cs673.superkids123.parents.model.Image;
import edu.bu.cs673.superkids123.parents.model.SystemTheme;

// TODO: Auto-generated Javadoc
/**
 * The Class ChildManager.
 */
public class ChildManager {

	/**
	 * Adds the child.
	 *
	 * @param child the child
	 * @return the int
	 */
	public static int addChild(Child child) {
		int result = -1;
		Transaction tx = null;
		
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {
			tx = session.beginTransaction();
			
			child.setActive(true);
			child.setLocked(false);

			result = (Integer) session.save(child);

			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return result;
	}

	/**
	 * Adds the child.
	 *
	 * @param name the name
	 * @param age the age
	 * @param sex the sex
	 * @param avatar the avatar
	 * @param level the level
	 * @param theme the theme
	 * @return the int
	 */
	public static int addChild(String name, int age, Sex sex, Image avatar,
			Level level, SystemTheme theme) {

		Child child = new Child();
		child.setName(name);
		child.setAge(age);
		child.setActive(true);
		child.setLocked(false);
		child.setSex(sex);
		if (sex == Sex.Female) {
			child.setImage(ParentSystemManager.getImageByFileName(ChildrenResource.imageGirlPrincess));
		} else {
			child.setImage(ParentSystemManager.getImageByFileName(ChildrenResource.imageBoy));
		}
		
		avatar.addChild(child);
		level.addChild(child);
		theme.addChild(child);

		return addChild(child);
	}

	/**
	 * Adds the child.
	 *
	 * @param name the name
	 * @param age the age
	 * @param sex the sex
	 * @return the int
	 */
	public static int addChild(String name, int age, Sex sex) {

		Child child = new Child();
		child.setName(name);
		child.setAge(age);
		child.setActive(true);
		child.setLocked(false);
		child.setSex(sex);
		if (sex == Sex.Female) {
			child.setImage(ParentSystemManager.getImageByFileName(ChildrenResource.imageGirlPrincess));
		} else {
			child.setImage(ParentSystemManager.getImageByFileName(ChildrenResource.imageBoy));
		}

		return addChild(child);
	}

	/**
	 * Update child.
	 *
	 * @param child the child
	 */
	public static void updateChild(Child child) {
		
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {
			tx = session.beginTransaction();
			
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	
	
	
	/**
	 * Add | Update child avatar.
	 *
	 * @param child the child
	 * @param avatar the avatar
	 */
	public static void updateChildAvatar(Child child, Image avatar) {
		
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {
			tx = session.beginTransaction();
			avatar.addChild(child);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	/**
	 * Add | Update child level.
	 *
	 * @param child the child
	 * @param level the level
	 */
	public static void updateChildLevel(Child child, Level level) {
		
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			level.addChild(child);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	/**
	 * Update child theme.
	 *
	 * @param child the child
	 * @param theme the theme
	 */
	public static void updateChildTheme(Child child, SystemTheme theme) {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			theme.addChild(child);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	/**
	 * Adds the child achievement.
	 *
	 * @param child the child
	 * @param achievement the achievement
	 */
	public static void addChildAchievement(Child child, Achievement achievement) {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			child.getAchievements().add(achievement);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	/**
	 * Removes the selected achievement from the selected child.
	 * 
	 * @param child
	 * @param achievement
	 */
	public static void deleteChildAchievement(Child child, Achievement achievement) {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {
			tx = session.beginTransaction();
			child.getAchievements().remove(achievement);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	// ADD Child Activity : Activities here are save to generate report
	/**
	 * Adds the child activities.
	 *
	 * @param child the child
	 * @param activities the activities
	 */
	public static void addChildActivities(Child child, Set<Activity> activities) {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			child.setActivities(activities);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	/*
	 * ADD Child CompletedLesson : Lesson will be assigned to child based on the
	 * level. Level has many lessons and level is assigned to child .Child will
	 * see all lessons within that level(same as Game) Once child start the
	 * lesson, it will be recorded in the Completed lesson table if child
	 * finishes the lesson, update the isCompleted to true
	 */
	/**
	 * Adds the child completed lesson.
	 *
	 * @param child the child
	 * @param completedLesson the completed lesson
	 */
	public static void addChildCompletedLesson(Child child,
			CompletedLesson completedLesson) {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			child.getCompletedLesson().add(completedLesson);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	/*
	 * ADD Child CompletedGames : Game will be assigned to child based on the
	 * level . Level has many Games and level is assigned to child. Child will
	 * see all Games within that level(same as Lesson) Once child start the
	 * Game, it will be recorded in the Completed Games table if child finishes
	 * the Game, update the isCompleted to true
	 */
	/**
	 * Adds the child completed game.
	 *
	 * @param child the child
	 * @param completedGame the completed game
	 */
	public static void addChildCompletedGame(Child child,
			CompletedGame completedGame) {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			child.getCompletedGames().add(completedGame);
			session.update(child);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	/**
	 * Gets the child by id.
	 *
	 * @param id the id
	 * @return the child by id
	 */
	public static Child getChildById(int id) {
		Child child = null;
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			Criteria criteria = session.createCriteria(Child.class);
			criteria.add(Restrictions.eq("id", id)).setMaxResults(1);

			child = (Child) criteria.uniqueResult();

			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

		return child;

	}

	/**
	 * Gets the child by name and avatar id.
	 *
	 * @param name the name
	 * @param avatar the avatar
	 * @return the child by name and avatar id
	 */
	public static Child getChildByNameAndAvatarId(String name, Image avatar) {

		Child child = null;
		Child exampleChild = new Child();
		exampleChild.setName(name);
		avatar.addChild(exampleChild);
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			Example example = Example.create(exampleChild);

			Criteria criteria = session.createCriteria(Child.class)
					.add(example);

			child = (Child) criteria.uniqueResult();

			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

		return child;

	}

	/**
	 * Gets the child by name.
	 *
	 * @param name the name
	 * @return the child by name
	 */
	public static Child getChildByName(String name) {
		Child child = null;
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			Criteria criteria = session.createCriteria(Child.class);
			criteria.add(Restrictions.eq("name", name)).setMaxResults(1);

			child = (Child) criteria.uniqueResult();

			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

		return child;

	}

	/**
	 * Gets the children.
	 *
	 * @return the children
	 */
	@SuppressWarnings("unchecked")
	public static List<Child> getChildren() {
		List<Child> children = null;
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			Query query = session.createQuery("From Child");

			children = (List<Child>) query.list();

			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

		return children;

	}

	/*
	 * Delete child: Note this will delete Child from database, this will be
	 * used only for testing purposes, Deleting a child on the system should be
	 * by updating child isActive to false
	 */
	/**
	 * Delete child.
	 *
	 * @param child the child
	 */
	public static void DeleteChild(Child child) {

		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();

		try {

			tx = session.beginTransaction();
			if (child != null) {
				session.delete(child);
			}

			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

	}

	/**
	 * Gets the child count.
	 *
	 * @return the child count
	 */
	public static Long getChildCount() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		try {
			Criteria criteria = session.createCriteria(Child.class);
			return (Long) criteria.setProjection(Projections.rowCount())
					.uniqueResult();
		} catch (HibernateException e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return Long.valueOf(0);
	}
	
	
}
